package com.example.netty.chatSystem.client;

import com.example.netty.chatSystem.channelService.ChannelService;
import com.example.netty.chatSystem.currency.LengthField;
import com.example.netty.chatSystem.message.*;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;

@Slf4j
public class Client {
    public static void main(String[] args) throws InterruptedException {
        NioEventLoopGroup group = new NioEventLoopGroup();
        AtomicBoolean atomicBoolean = new AtomicBoolean(false);
        CountDownLatch countDownLatch = new CountDownLatch(1);
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group);
            bootstrap.channel(NioSocketChannel.class);
            bootstrap.handler(new ChannelInitializer<SocketChannel>() {

                @Override
                protected void initChannel(SocketChannel socketChannel) throws Exception {
                    socketChannel.pipeline().addLast(new LengthField());
                    socketChannel.pipeline().addLast(new LoggingHandler(LogLevel.DEBUG));
                    socketChannel.pipeline().addLast(new MessageCodec1());

                    //用来判断是不是 读空闲时间过长 或 写时间过长
                    //5s 内没有收到 channel 的数据 IdleState#WRITER_IDLE 事件
                    socketChannel.pipeline().addLast(new IdleStateHandler(
                            0,3,0));
                    //ChannelDuplexHandler 可以同时处理 入站和出站
                    socketChannel.pipeline().addLast(new ChannelDuplexHandler(){
                        //用来触发特殊事件
                        @Override
                        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
                            IdleStateEvent event = (IdleStateEvent) evt;
                            //触发了读空闲事件
                            if (event.state() == IdleState.WRITER_IDLE) {
                                log.debug("3s 未写出数据");
                                ctx.writeAndFlush(new PingMessage());
                            }
                        }
                    });

                    //socketChannel.pipeline().addLast(new StringEncoder());
                    socketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter(){
                        @Override
                        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                            log.debug("msg: {}",msg);
                            if (msg instanceof LoginResult){
                                LoginResult loginResult = (LoginResult) msg;
                                atomicBoolean.set(loginResult.isResult());
                            }
                            countDownLatch.countDown();
                        }

                        @Override
                        public void channelActive(ChannelHandlerContext ctx) throws Exception {
                            new Thread(() -> {
                                Scanner scanner = new Scanner(System.in);
                                String name = null;
                                String password = null;
                                while (!atomicBoolean.get()){
                                    System.out.println("请输入用户名");
                                    name = scanner.nextLine();
                                    System.out.println("请输入密码");
                                    password = scanner.nextLine();
                                    LoginMessage loginMessage = new LoginMessage(name,password);
                                    ctx.writeAndFlush(loginMessage);
                                    System.out.println("等待验证");
                                    try {
                                        System.out.println("唤醒");
                                        countDownLatch.await();
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                }

                                while (true){
                                    System.out.println("==============");
                                    System.out.println("send to message");
                                    System.out.println("==============");
                                    String command = scanner.nextLine();
                                    String[] s = command.split(" ");
                                    switch (s[0]){
                                        case "send":
                                            ctx.writeAndFlush(new SendMessage(name,s[1],s[2]));
                                            break;
                                        case "quit":
                                            ctx.channel().close();
                                            return;
                                    }

                                }
                            },"system.in").start();
                        }
                    });
                }
            });
            Channel channel = bootstrap.connect("localhost", 8080).sync().channel();
            channel.closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            group.shutdownGracefully();
        }
    }
}
